/*
 * Copyright (c) 2019-2020, NVIDIA CORPORATION.  All rights reserved.
 *
 * NVIDIA Corporation and its licensors retain all intellectual property
 * and proprietary rights in and to this software, related documentation
 * and any modifications thereto.  Any use, reproduction, disclosure or
 * distribution of this software and related documentation without an express
 * license agreement from NVIDIA Corporation is strictly prohibited.
 *
 */

/**
 * @file
 * <b>Defines NVIDIA DeepStream Metadata Structures </b>
 *
 * @b Description: This file defines DeepStream metadata structures.
 */

/**
 * @defgroup  metadata_structures  Metadata Structures
 *
 * Define structures that hold metadata.
 * @ingroup NvDsMetaApi
 * @{
 */

#ifndef _NVDSMETA_NEW_H_
#define _NVDSMETA_NEW_H_

#include <stdbool.h>

#include "glib.h"
#include "gmodule.h"
#include "nvll_osd_struct.h"

#ifdef __cplusplus
extern "C"
{
#endif

/** Defines the number of additional fields available to the user
 in the metadata structure. */
#define MAX_USER_FIELDS 4

#define MAX_RESERVED_FIELDS 4
/** Defines the maximum size of an array for storing a text result. */
#define MAX_LABEL_SIZE 128
/** Defines the maximum number of elements that a given display meta
 can hold. */
#define MAX_ELEMENTS_IN_DISPLAY_META 16
/** Defines an untracked object ID. */
#define UNTRACKED_OBJECT_ID 0xFFFFFFFFFFFFFFFF

typedef GList NvDsFrameMetaList;
typedef GList NvDsUserMetaList;
typedef GList NvDsObjectMetaList;
typedef GList NvDisplayMetaList;
typedef GList NvDsClassifierMetaList;
typedef GList NvDsLabelInfoList;
typedef GList NvDsMetaList;
typedef void NvDsElementMeta;

/* In the following doc comment:
 * @param[in]  user_data    A pointer to user-specific data. For internal use
 *                          only; in applications it must be set to NULL.
 */
/**
 * \brief  Defines the type of a callback to copy metadata.
 *
 * The callback is passed pointers to source metadata. It allocates the
 * required memory, copies the content from the source metadata and returns
 * a pointer to the destination.
 *
 * @param[in]  data         A pointer to the source metadata.
 * @param[in]  user_data    A pointer to user-specific data.
 */
typedef gpointer (*NvDsMetaCopyFunc) (gpointer data, gpointer user_data);

/**
 * \brief  Defines the type of a callback to free metadata.
 *
 * The callback is passed a pointer to metadata created by NvDsMetaCopyFunc().
 * It frees the metadata and
 * any other resources that the metadata uses.
 *
 * @param[in]  data         A pointer to the metadata to be freed.
 * @param[in]  user_data    A pointer to user-specific data.
 */
typedef void (*NvDsMetaReleaseFunc) (gpointer data, gpointer user_data);

/**
 * Specifies the type of metadata. All metadata types are subtypes of
 * @ref NvDsMetaType. Members that represent NVIDIA-defined types are
 * in the range from @ref NVDS_BATCH_META to @ref NVDS_START_USER_META.
 * User-defined types may be assigned values greater than or equal to
 * @ref NVDS_START_USER_META.
 */
typedef enum {
  NVDS_INVALID_META=-1,
  /** Specifies metadata type for formed batch. */
  NVDS_BATCH_META = 1,
  /** Specifies metadata type for frame. */
  NVDS_FRAME_META,
  /** Specifies metadata type for a detected object. */
  NVDS_OBJ_META,
  /** Specifies metadata type for display. */
  NVDS_DISPLAY_META,
  /** Specifies metadata type for an object classifier. */
  NVDS_CLASSIFIER_META,
  /** Specifies metadata type for a label assigned by a classifier. */
  NVDS_LABEL_INFO_META,
  /** Reserved for internal use. */
  NVDS_USER_META,
  /** Specifies metadata type for a payload generated by a message converter. */
  NVDS_PAYLOAD_META,
  /** Specifies metadata type for a payload generated by a message broker. */
  NVDS_EVENT_MSG_META,
  /** Specifies metadata type for an optical flow. */
  NVDS_OPTICAL_FLOW_META,
  /** Specifies metadata type for a latency measurement. */
  NVDS_LATENCY_MEASUREMENT_META,
  /** Specifies metadata type for raw inference output attached by Gst-nvinfer.
   @see NvDsInferTensorMeta for details. */
  NVDSINFER_TENSOR_OUTPUT_META,
  /** Specifies metadata type for segmentation model output attached by
   Gst-nvinfer. @see NvDsInferSegmentationMeta for details. */
  NVDSINFER_SEGMENTATION_META,
 /** Specifies metadata type for JPEG-encoded object crops.
  * See the deepstream-image-meta-test app for details. */
  NVDS_CROP_IMAGE_META,
  /** metadata type to be set for tracking previous frames */
  NVDS_TRACKER_PAST_FRAME_META,
  /** Specifies metadata type for formed audio batch. */
  NVDS_AUDIO_BATCH_META,
  /** Specifies metadata type for audio frame. */
  NVDS_AUDIO_FRAME_META,
  /** Reserved field */
  NVDS_RESERVED_META = 4095,
  /**
   * Specifies the start of a range of enum values that represent types of
   * NVIDIA-defined Gst metas. The range is from NVDS_GST_CUSTOM_META to
   * NVDS_GST_CUSTOM_META+4096, inclusive.
   */
  NVDS_GST_CUSTOM_META = 4096,
  /** Start adding user specific meta types from here */
  /**
   * Specifies the start of a range of enum values that represent custom
   * (application-specific) Gst meta types. A custom meta type may be assigned
   * any enum value equal to or larger than this.
   *
   * Such Gst metas may be attached by GStreamer plugins upstream from
   * Gst-nvstreammux. They may have any contents that is a superset of
   * the metadata in an @ref NvDsFrameMeta.
   */
  NVDS_START_USER_META = NVDS_GST_CUSTOM_META + 4096 + 1,
  NVDS_FORCE32_META = 0x7FFFFFFF
} NvDsMetaType;

/**
 * Holds unclipped positional bounding box coordinates of the object processed
 * by the component.
 */
typedef struct _NvDsComp_BboxInfo
{
  NvBbox_Coords org_bbox_coords;
} NvDsComp_BboxInfo;

/**
 * Holds information about a given metadata pool.
 */
typedef struct _NvDsMetaPool {
  NvDsMetaType meta_type;
  guint max_elements_in_pool;
  guint element_size;
  guint num_empty_elements;
  guint num_full_elements;
  NvDsMetaList * empty_list;
  NvDsMetaList * full_list;
  NvDsMetaCopyFunc copy_func;
  NvDsMetaReleaseFunc release_func;
}NvDsMetaPool;

/**
 * Holds information about base metadata of a given metadata type.
 */
typedef struct _NvDsBaseMeta {
  /** Holds a pointer to batch_meta @ref NvDsBatchMeta. */
  struct _NvDsBatchMeta *batch_meta;
  /** Holds the metadata type of this metadata element. */
  NvDsMetaType meta_type;
  /** Holds a pointer to a user context. */
  void * uContext;
  /** Holds a user-defined copy function. The function is called to copy
   or transform metadata from one buffer to another. @a meta_data and
   @a user_data are passed as arguments. */
  NvDsMetaCopyFunc copy_func;
  /** Holds a user-defined release function. The function is called
   when @a meta_data is to be released. */
  NvDsMetaReleaseFunc release_func;
} NvDsBaseMeta;

/**
 * Holds information about a formed batch containing frames from different
 * sources.
 */
typedef struct _NvDsBatchMeta {
  NvDsBaseMeta base_meta;
  /** Holds the maximum number of frames in the batch. */
  guint max_frames_in_batch;
  /** Holds the number of frames now in the batch. */
  guint num_frames_in_batch;
  /** Holds a pointer to a pool of pointers of type @ref NvDsFrameMeta,
   representing a pool of frame metas. */
  NvDsMetaPool *frame_meta_pool;
  /** Holds a pointer to a pool of pointers of type NvDsObjMeta,
   representing a pool of object metas. */
  NvDsMetaPool *obj_meta_pool;
  /** Holds a pointer to a pool of pointers of type @ref NvDsClassifierMeta,
   representing a pool of classifier metas. */
  NvDsMetaPool *classifier_meta_pool;
  /** Holds a pointer to a pool of pointers of type @ref NvDsDisplayMeta,
   representing a pool of display metas. */
  NvDsMetaPool *display_meta_pool;
  /** Holds a pointer to a pool of pointers of type @ref NvDsUserMeta,
   representing a pool of user metas. */
  NvDsMetaPool *user_meta_pool;
  /** Holds a pointer to a pool of pointers of type @ref NvDsLabelInfo,
   representing a pool of label metas. */
  NvDsMetaPool *label_info_meta_pool;
  /** Holds a pointer to a list of pointers of type NvDsFrameMeta
   or NvDsAudioFrameMeta (when the batch represent audio batch),
   representing frame metas used in the current batch.
   */
  NvDsFrameMetaList *frame_meta_list;
  /** Holds a pointer to a list of pointers of type NvDsUserMeta,
   representing user metas in the current batch. */
  NvDsUserMetaList *batch_user_meta_list;
  /** Holds a lock to be set before accessing metadata to avoid
   simultaneous update by multiple components. */
  GRecMutex meta_mutex;
  /** Holds an array of user-specific batch information. */
  gint64 misc_batch_info[MAX_USER_FIELDS];
  /** For internal use. */
  gint64 reserved[MAX_RESERVED_FIELDS];
} NvDsBatchMeta;

/**
 * Holds metadata for a frame in a batch.
 */
typedef struct _NvDsFrameMeta {
  /** Holds the base metadata for the frame. */
  NvDsBaseMeta base_meta;
  /** Holds the pad or port index of the Gst-streammux plugin for the frame
   in the batch. */
  guint pad_index;
  /** Holds the location of the frame in the batch. The frame's
   @ref NvBufSurfaceParams are at index @a batch_id in the @a surfaceList
   array of @ref NvBufSurface. */
  guint batch_id;
  /** Holds the current frame number of the source. */
  gint frame_num;
  /** Holds the presentation timestamp (PTS) of the frame. */
  guint64 buf_pts;
  /** Holds the ntp timestamp. */
  guint64 ntp_timestamp;
  /** Holds the source IDof the frame in the batch, e.g. the camera ID.
   It need not be in sequential order. */
  guint source_id;
  /** Holds the number of surfaces in the frame, required in case of
   multiple surfaces in the frame. */
  gint num_surfaces_per_frame;
  /* Holds the width of the frame at input to Gst-streammux. */
  guint source_frame_width;
  /* Holds the height of the frame at input to Gst-streammux. */
  guint source_frame_height;
  /* Holds the surface type of the subframe, required in case of
   multiple surfaces in the frame. */
  guint surface_type;
  /* Holds the surface index of tje subframe, required in case of
   multiple surfaces in the frame. */
  guint surface_index;
  /** Holds the number of object meta elements attached to current frame. */
  guint num_obj_meta;
  /** Holds a Boolean indicating whether inference is performed on the frame. */
  gboolean bInferDone;
  /** Holds a pointer to a list of pointers of type @ref NvDsObjectMeta
   in use for the frame. */
  NvDsObjectMetaList *obj_meta_list;
  /** Holds a pointer to a list of pointers of type @ref NvDsDisplayMeta
   in use for the frame. */
  NvDisplayMetaList *display_meta_list;
  /** Holds a pointer to a list of pointers of type @ref NvDsUserMeta
   in use for the frame. */
  NvDsUserMetaList *frame_user_meta_list;
  /** Holds additional user-defined frame information. */
  gint64 misc_frame_info[MAX_USER_FIELDS];
  /** For internal use. */
  gint64 reserved[MAX_RESERVED_FIELDS];
} NvDsFrameMeta;

/**
 * Holds metadata for an object in the frame.
 */
typedef struct _NvDsObjectMeta {
  NvDsBaseMeta base_meta;
  /** Holds a pointer to the parent @ref NvDsObjectMeta. Set to NULL if
   no parent exists. */
  struct _NvDsObjectMeta *parent;
  /** Holds a unique component ID that identifies the metadata
   in this structure. */
  gint unique_component_id;
  /** Holds the index of the object class inferred by the primary
   detector/classifier. */
  gint class_id;
  /** Holds a unique ID for tracking the object. @ref UNTRACKED_OBJECT_ID
   indicates that the object has not been tracked. */
  guint64 object_id;
  /** Holds a structure containing bounding box parameters of the object when
    detected by detector. */
  NvDsComp_BboxInfo detector_bbox_info;
  /** Holds a structure containing bounding box coordinates of the object when
   * processed by tracker. */
  NvDsComp_BboxInfo tracker_bbox_info;
  /** Holds a confidence value for the object, set by the inference
   component. confidence will be set to -0.1, if "Group Rectangles" mode of
   clustering is chosen since the algorithm does not preserve confidence
   values. Also, for objects found by tracker and not inference component,
   confidence will be set to -0.1 */
  gfloat confidence;
  /** Holds a confidence value for the object set by nvdcf_tracker.
   * tracker_confidence will be set to -0.1 for KLT and IOU tracker */
  gfloat tracker_confidence;
  /** Holds a structure containing positional parameters of the object
   * processed by the last component that updates it in the pipeline.
   * e.g. If the tracker component is after the detector component in the
   * pipeline then positinal parameters are from tracker component.
   * Positional parameters are clipped so that they do not fall outside frame
   * boundary. Can also be used to overlay borders or semi-transparent boxes on
   * objects. @see NvOSD_RectParams. */
  NvOSD_RectParams rect_params;
  /** Holds mask parameters for the object. This mask is overlayed on object
   * @see NvOSD_MaskParams. */
  NvOSD_MaskParams mask_params;
  /** Holds text describing the object. This text can be overlayed on the
   standard text that identifies the object. @see NvOSD_TextParams. */
  NvOSD_TextParams text_params;
  /** Holds a string describing the class of the detected object. */
  gchar obj_label[MAX_LABEL_SIZE];
  /** Holds a pointer to a list of pointers of type @ref NvDsClassifierMeta. */
  NvDsClassifierMetaList *classifier_meta_list;
  /** Holds a pointer to a list of pointers of type @ref NvDsUserMeta. */
  NvDsUserMetaList *obj_user_meta_list;
  /** Holds additional user-defined object information. */
  gint64 misc_obj_info[MAX_USER_FIELDS];
  /** For internal use. */
  gint64 reserved[MAX_RESERVED_FIELDS];
}NvDsObjectMeta;

/**
 * Holds classifier metadata for an object.
 */
typedef struct _NvDsClassifierMeta {
  NvDsBaseMeta base_meta;
  /** Holds the number of outputs/labels produced by the classifier. */
  guint num_labels;
  /** Holds a unique component ID for the classifier metadata. */
  gint unique_component_id;
  /** Holds a pointer to a list of pointers of type @ref NvDsLabelInfo. */
  NvDsLabelInfoList *label_info_list;
} NvDsClassifierMeta;

/**
 * Holds label metadata for the classifier.
 */
typedef struct _NvDsLabelInfo {
  NvDsBaseMeta base_meta;
  /** Holds the number of classes of the given label. */
  guint num_classes;
  /** Holds an string describing the label of the classified object. */
  gchar result_label[MAX_LABEL_SIZE];
  /** Holds a pointer to the result label if its length exceeds MAX_LABEL_SIZE bytes. */
  gchar *pResult_label;
  /** Holds the class UD of the best result. */
  guint result_class_id;
  /** Holds the label ID in case there are multiple label classifiers. */
  guint label_id;
  /** Holds the probability of best result. */
  gfloat result_prob;
} NvDsLabelInfo;

/**
 * Holds display metadata that the user can specify in the frame.
 */
typedef struct NvDsDisplayMeta {
  NvDsBaseMeta base_meta;
  /** Holds the number of rectangles described. */
  guint num_rects;
  /** Holds the number of labels (strings) described. */
  guint num_labels;
  /** Holds the number of lines described. */
  guint num_lines;
  /** Holds the number of arrows described. */
  guint num_arrows;
  /** Holds the number of circles described. */
  guint num_circles;
  /** Holds an array of positional parameters for rectangles.
   Used to overlay borders or semi-transparent rectangles,
   as required by the application. @see NvOSD_RectParams. */
  NvOSD_RectParams rect_params[MAX_ELEMENTS_IN_DISPLAY_META];
  /** Holds an array of text parameters for user-defined strings that can be
   overlayed using this structure. @see NvOSD_TextParams. */
  NvOSD_TextParams text_params[MAX_ELEMENTS_IN_DISPLAY_META];
  /** Holds an array of line parameters that the user can use to draw polygons
   in the frame, e.g. to show a RoI in the frame. @see NvOSD_LineParams. */
  NvOSD_LineParams line_params[MAX_ELEMENTS_IN_DISPLAY_META];
  /** Holds an array of arrow parameters that the user can use to draw arrows
   in the frame. @see NvOSD_ArrowParams */
  NvOSD_ArrowParams arrow_params[MAX_ELEMENTS_IN_DISPLAY_META];
  /** Holds an array of circle parameters that the user can use to draw circles
   in the frame. @see NvOSD_CircleParams */
  NvOSD_CircleParams circle_params[MAX_ELEMENTS_IN_DISPLAY_META];
  /** Holds an array of user-defined OSD metadata. */
  gint64 misc_osd_data[MAX_USER_FIELDS];
  /** For internal use. */
  gint64 reserved[MAX_RESERVED_FIELDS];
} NvDsDisplayMeta;

/**
 * Holds user metadata.
 */
typedef struct _NvDsUserMeta {
  NvDsBaseMeta base_meta;
  /** Holds a pointer to user data to be attached.
   See the deepstream-user-metadata-test example for usage. */
  void *user_meta_data;
} NvDsUserMeta;

/**
 * Acquires a lock before updating metadata.
 *
 * @param[in] batch_meta    A pointer to the NvDsBatchMeta structure
 *                          to be locked.
 */
void nvds_acquire_meta_lock (NvDsBatchMeta *batch_meta);

/**
 * Releases the lock after updating metadata.
 *
 * @param[in] batch_meta    A pointer to NvDsBatchMeta structure to be unlocked.
 */
void nvds_release_meta_lock (NvDsBatchMeta *batch_meta);

/**
 * Creates a batch metadata structure for a batch of specified size.
 *
 * @param[in] max_batch_size    The maximum number of frames in the batch.
 * @ return  A pointer to the created structure.
 */
NvDsBatchMeta *nvds_create_batch_meta(guint max_batch_size);

/**
 * Destroys a batch metadata structure.
 *
 * @param[in] batch_meta    A pointer to batch metadata structure
 *                          to be destroyed.
 * @returns  True if the object was successfully destroyed, or false otherwise.
 */
gboolean nvds_destroy_batch_meta(NvDsBatchMeta *batch_meta);

/**
 * \brief  Acquires a frame meta from a batch's frame meta pool.
 *
 * You must acquire a frame meta before you can fill it with frame metadata.
 *
 * @param[in] batch_meta    A pointer to batch meta from which to acquire
 *                          a frame meta.
 *
 * @return  A pointer to the acquired frame meta.
 */
NvDsFrameMeta *nvds_acquire_frame_meta_from_pool (NvDsBatchMeta *batch_meta);

/**
 * Adds a frame meta to a batch meta.
 *
 * @param[in] batch_meta    A pointer to the NvDsBatchMeta to which
 *                          @a frame_meta is to be added.
 * @param[in] frame_meta    A pointer to a frame meta to be added to
 *                          @a batch_meta.
 */
void nvds_add_frame_meta_to_batch(NvDsBatchMeta * batch_meta,
    NvDsFrameMeta * frame_meta);

/**
 * Removes a frame meta from a batch meta.
 *
 * @param[in] batch_meta    A pointer to the batch meta from which @a frame_meta
 *                          is to be removed.
 * @param[in] frame_meta    A pointer to the frame meta to be removed from
 *                          @a batch_meta.
 */
void nvds_remove_frame_meta_from_batch (NvDsBatchMeta *batch_meta,
    NvDsFrameMeta * frame_meta);

/**
 * @brief  Acquires an object meta from a batch meta's object meta pool.
 *
 * You must acquire an object meta before you can fill it with object metadata.
 *
 * @param[in] batch_meta    A pointer to the batch meta from which to acquire
 *                          an object meta.
 *
 * @return  A pointer to the acquired object meta.
 */
NvDsObjectMeta *nvds_acquire_obj_meta_from_pool (NvDsBatchMeta *batch_meta);

/**
 * @brief  Adds an object meta to a frame meta.
 *
 * You must acquire the object meta with nvds_acquire_object_meta_from_pool()
 * and fill it with metadata before you add to to the frame meta.
 *
 * @param[in] frame_meta    A pointer to the frame meta to which @a obj_meta
 *                          is to be added.
 * @param[in] obj_meta      A pointer to an object meta to be added to @a frame_meta.
 * @param[in] obj_parent    A pointer to the this object meta's parent object meta.
 *                          This pointer is stored in @a obj_meta->parent.
 */
void nvds_add_obj_meta_to_frame(NvDsFrameMeta * frame_meta,
    NvDsObjectMeta *obj_meta, NvDsObjectMeta *obj_parent);

/**
 * Removes an object meta from the frame meta to which it is attached.
 *
 * @param[in] frame_meta    A pointer to frame meta from which @a obj_meta
 *                          is to be removed.
 * @param[in] obj_meta      A pointer to the object meta to be removed from
 *                          @a frame_meta.
 */
void nvds_remove_obj_meta_from_frame (NvDsFrameMeta * frame_meta,
    NvDsObjectMeta *obj_meta);

/**
 * @brief  Acquires a classifier meta from a batch meta's classifier meta pool.
 *
 * You must acquire a classifier meta from the classifier meta pool before you
 * can fill it with classifier metadata.
 *
 * @param[in] batch_meta    A pointer to the batch meta from which to acquire
 *                          a classifier meta.
 *
 * @return  The classifier meta acquired from the batch meta's
 *  classifier meta pool.
 */
NvDsClassifierMeta *nvds_acquire_classifier_meta_from_pool(
    NvDsBatchMeta *batch_meta);

/**
 * @brief  Adds a classifier meta the appropriate object meta.
 *
 * You must acquire a classifier meta with
 * nvds_acquire_classifier_meta_from_pool() and fill it with
 * classifier metadata before you add it to the object metadata.
 *
 * @param[in] obj_meta          A pointer to the object meta to which
 *                              @a classifier_meta is to be added.
 * @param[in] classifier_meta   A pointer to the classifier meta to be added
 *                              to @a obj_meta.
 */
void nvds_add_classifier_meta_to_object(NvDsObjectMeta *obj_meta,
    NvDsClassifierMeta * classifier_meta);

/**
 * Removes a classifier meta from the object meta to which it is attached.
 *
 * @param[in] obj_meta          A pointer to the object meta from which
 *                              @a classifier_meta is to be removed.
 * @param[in] classifier_meta   A pointer to the classifier meta to be removed
 *                              from @a obj_meta.
 */
void nvds_remove_classifier_meta_from_obj (NvDsObjectMeta * obj_meta,
    NvDsClassifierMeta *classifier_meta);

/**
 * @brief  Acquires a display meta from a batch meta's display meta pool.
 *
 * You must acquire a display meta before you can fill it with display metadata.
 *
 * @param[in] batch_meta    A pointer to the batch meta from which to acquire
 *                          a display meta.
 *
 * @return  The display meta acquired from the batch meta's display meta pool.
 */
NvDsDisplayMeta *nvds_acquire_display_meta_from_pool (
    NvDsBatchMeta *batch_meta);

/**
 * @brief  Adds a display meta to the appropriate frame meta.
 *
 * You must acquire a display meta with nvds_)acquire_display_meta_from_pool()
 * and fill it with display metadata before you can add it to the frame meta.
 *
 * @param[in] frame_meta    A pointer to frame meta to which @a display_meta
 *                          is to be added.
 * @param[in] display_meta  A pointer to the display meta to be added to
 *                          @a frame_meta.
 */
void nvds_add_display_meta_to_frame(NvDsFrameMeta * frame_meta,
    NvDsDisplayMeta * display_meta);

/**
 * Removes a display meta from the frame meta to which it is attached.
 *
 * @param[in] frame_meta    A pointer to the frame meta from which
 *                          @a display_meta is to be removed.
 * @param[in] display_meta  A pointer to the display meta to be removed from
 *                          @a frame_meta.
 */
void nvds_remove_display_meta_from_frame (NvDsFrameMeta * frame_meta,
    NvDsDisplayMeta *display_meta);

/**
 * @brief  Acquires a label info meta from a batch meta's label info meta pool.
 *
 * You must acquire a label info meta before you can fill it and add it to a
 * classifier meta.
 *
 * @param[in] batch_meta    A pointer to the batch meta from which to acquire
 *                          a label info meta.
 *
 * @return  The label info meta acquired from the batch meta's
 *  label info meta pool.
 */
NvDsLabelInfo *nvds_acquire_label_info_meta_from_pool (
    NvDsBatchMeta *batch_meta);

/**
 * Adds a label info meta to a classifier meta.
 *
 * @param[in] classifier_meta   A pointer to the classifier meta to which
 *                              @a label_info_meta is to be added.
 * @param[in] label_info_meta   A pointer to the label info meta to be added
 *                              to @a classifier_meta.
 */
void nvds_add_label_info_meta_to_classifier(
    NvDsClassifierMeta *classifier_meta, NvDsLabelInfo * label_info_meta);

/**
 * Removes a label info meta from the classifier meta to which it is attached.
 *
 * @param[in] classifier_meta   A pointer to the classifier meta from which
 *                              @a label_info_meta is to be removed.
 * @param[in] label_info_meta   A pointer to the label info meta to be removed
 *                              from @a classifier_meta.
 */
void nvds_remove_label_info_meta_from_classifier (
    NvDsClassifierMeta *classifier_meta, NvDsLabelInfo *label_info_meta);

/**
 * Add a user meta to a batch meta.
 *
 * @param[in] batch_meta    A pointer to batch meta to which @a user_meta
 *                          is to be added.
 * @param[in] user_meta     A pointer to a user meta to be added to
 *                          @a batch_meta.
 */
void nvds_add_user_meta_to_batch(NvDsBatchMeta * batch_meta,
    NvDsUserMeta * user_meta);

/**
 * Add a user meta to a frame meta.
 *
 * @param[in] frame_meta    A pointer to the frame meta to which @a user_meta
 *                          is to be added.
 * @param[in] user_meta     A pointer to a user meta to be added to
 *                          @a frame_meta.
 */
void nvds_add_user_meta_to_frame(NvDsFrameMeta * frame_meta,
    NvDsUserMeta * user_meta);

/**
 * Add a user meta user to an object meta.
 *
 * @param[in] obj_meta      A pointer to the object meta to which @a user_meta
 *                          is to be added.
 * @param[in] user_meta     A pointer to the user meta to be added to
 *                          @a obj_meta.
 */
void nvds_add_user_meta_to_obj(NvDsObjectMeta * obj_meta,
    NvDsUserMeta * user_meta);

/**
 * @brief  Acquires a user meta from a batch meta's user meta pool.
 *
 * You must acquire a user meta before you can fill it with user metdata and
 * add it to a batch, frame, or object meta (call nvds_add_user_data_to_batch(),
*  nvds_add_user_data_to_frame(), or nvds_add_user_data_to_obj()).
 *
 * @param[in] batch_meta    A pointer to the batch meta from which to acquire
 *                          a user meta.
 */
NvDsUserMeta *nvds_acquire_user_meta_from_pool (NvDsBatchMeta *batch_meta);

/**
 * Removes a user meta from a batch meta to which it is attached.
 *
 * @param[in] batch_meta    A pointer to the batch meta from which @a user_meta
 *                          is to be removed.
 * @param[in] user_meta     A pointer to the user meta to be removed from
 *                          @a batch_meta.
 *
 * returns acquired @ref NvDsUserMeta pointer from user meta pool
 */
void nvds_remove_user_meta_from_batch(NvDsBatchMeta * batch_meta,
    NvDsUserMeta * user_meta);

/**
 * Removes a user meta from a frame meta to which it is attached.
 *
 * @param[in] frame_meta    A pointer to the frame meta from which @a user_meta
 *                          is to be removed.
 * @param[in] user_meta     A pointer to the user meta to be removed from
 *                          @a frame_meta.
 */
void nvds_remove_user_meta_from_frame(NvDsFrameMeta * frame_meta,
    NvDsUserMeta * user_meta);

/**
 * Removes a user meta from an object meta to which it is attached.
 *
 * @param[in] obj_meta      A pointer to the object meta from which @a user_meta
 *                          is to be removed.
 * @param[in] user_meta     A pointer to the user to be removed from
 *                          @a obj_meta.
 */
void nvds_remove_user_meta_from_object(NvDsObjectMeta * obj_meta,
    NvDsUserMeta * user_meta);

/**
 * A debugging function; prints current metadata information available after
 * inference. This function should be called after inference.
 *
 * @param[in] batch_meta    A pointer to a batch meta from which to
 *                          print information.
 * @return
 */
gboolean nvds_get_current_metadata_info(NvDsBatchMeta *batch_meta);

/**
 * @brief  Copies or transforms meta data from one buffer to another.
 *
 * @param[in] data      A pointer to a batch meta (of type @ref NvDsBatchMeta),
 *                      cast to @c gpointer.
 * @param[in] user_data Currently not in use and should be set to NULL.
 *
 * @return A pointer to a metadata structure, to be cast to type NvDsBatchMeta.
 */
gpointer nvds_batch_meta_copy_func (gpointer data, gpointer user_data);

/**
 * Releases metadata from a batch meta.
 *
 * @param[in] data      A pointer to a batch meta (type @ref NvDsBatchMeta),
 *                      cast to @c gpointer.
 * @param[in] user_data Currently not in use and should be set to NULL.
 */
void nvds_batch_meta_release_func(gpointer data, gpointer user_data);

/**
 * Returns a pointer to a specified frame meta in the frame meta list.
 *
 * @param[in] frame_meta_list   A pointer to a list of pointers to frame metas.
 * @param[in] index             The index of the frame meta to be returned.
 *
 * @return  A pointer to the @a index'th frame meta in the frame meta list.
 */
NvDsFrameMeta *nvds_get_nth_frame_meta (NvDsFrameMetaList *frame_meta_list,
    guint index);

/**
 * Removes all of the frame metadata attached to a batch meta.
 *
 * @param[in] batch_meta    A pointer to the batch whose frame meta list
 *                          is to be cleared.
 * @param[in] meta_list     A pointer to the frame meta list to be cleared.
 */
void nvds_clear_frame_meta_list(NvDsBatchMeta *batch_meta,
    NvDsFrameMetaList *meta_list);

/**
 * Removes all the object metadata attached to a frame meta.
 *
 * @param[in] frame_meta    A pointer to the frame meta whose object meta list
 *                          is to be cleared.
 * @param[in] meta_list     A pointer to the object meta list to be cleared.
 */
void nvds_clear_obj_meta_list(NvDsFrameMeta *frame_meta,
    NvDsObjectMetaList *meta_list);

/**
 * Removes all of the classifier metadata attached to an object meta.
 *
 * @param[in] obj_meta A pointer to @ref NvDsObjectMeta from which @a
 *            NvDsClassifierMetaList needs to be cleared
 * @param[in] meta_list A pointer to @ref NvDsClassifierMetaList which needs to
 *            be cleared
 */
void nvds_clear_classifier_meta_list(NvDsObjectMeta *obj_meta,
    NvDsClassifierMetaList *meta_list);

/**
 * Removes all of the label info metadata attached to a classifier meta.
 *
 * @param[in] classifier_meta   A pointer to the classifier meta whose
 *                              label info meta list is to be cleared.
 * @param[in] meta_list         A pointer to the label info meta list to be
 *                              cleared.
 */
void nvds_clear_label_info_meta_list(NvDsClassifierMeta *classifier_meta,
    NvDsLabelInfoList *meta_list);

/**
 * Removes all of the display metadata attached to a frame meta.
 *
 * @param[in] frame_meta    A pointer to the frame meta whose display meta list
 *                          is to be cleared.
 * @param[in] meta_list     A pointer to the display meta list to be cleared.
 */
void nvds_clear_display_meta_list(NvDsFrameMeta *frame_meta,
    NvDisplayMetaList *meta_list);

/**
 * Removes all of the user metadata attached to the batch meta.
 *
 * @param[in] batch_meta    A pointer to the batch meta whose
 *                          user meta list is to be cleared.
 * @param[in] meta_list     A pointer to the user meta list to be
 *            cleared
 */
void nvds_clear_batch_user_meta_list(NvDsBatchMeta *batch_meta,
    NvDsUserMetaList *meta_list);

/**
 * Removes all of the user metadata attached to the frame meta.
 *
 * @param[in] frame_meta    A pointer to the frame meta whose
 *                          user meta list is to be cleared.
 * @param[in] meta_list     A pointer to the user meta list to be cleared.
 */
void nvds_clear_frame_user_meta_list(NvDsFrameMeta *frame_meta,
    NvDsUserMetaList *meta_list);

/**
 * Removes all of the user metadata attached to an object meta.
 *
 * @param[in] object_meta   A pointer to the object meta whose
 *                          user meta list is to be cleared.
 * @param[in] meta_list     A pointer to the user meta list to be cleared.
 */
void nvds_clear_obj_user_meta_list(NvDsObjectMeta *object_meta,
    NvDsUserMetaList *meta_list);

/**
 * Removes all of the metadata elements attached to a metadata list.
 *
 * @param[in] batch_meta    A pointer to a batch meta.
 * @param[in] meta_list     A pointer to meta list to be cleared.
 * @param[in] meta_pool     A pointer to the meta pool that contains
 *                          @a meta_list.
 * @return  A pointer to the updated meta list.
 */
NvDsMetaList *nvds_clear_meta_list(NvDsBatchMeta *batch_meta,
    NvDsMetaList *meta_list, NvDsMetaPool *meta_pool);

/**
 * \brief  Makes a deep copy of a frame meta to another frame meta.
 *
 * @param[in] src_frame_meta    A pointer to the source frame meta.
 * @param[in] dst_frame_meta    A pointer to the destination frame meta.
 */
void nvds_copy_frame_meta(NvDsFrameMeta *src_frame_meta,
    NvDsFrameMeta *dst_frame_meta);

/**
 * \brief  Makes a deep copy of an object meta to another object meta.
 *
 * @param[in] src_object_meta   A pointer to the source object meta.
 * @param[in] dst_object_meta   A pointer to the destination object meta.
 */
void nvds_copy_obj_meta(NvDsObjectMeta *src_object_meta,
    NvDsObjectMeta *dst_object_meta);

/**
 * \brief  Makes a deep copy of a classifier meta to another classifier meta.
 *
 * @param[in] src_classifier_meta   A pointer to the source classifier meta.
 * @param[in] dst_classifier_meta A pointer to the destination classifier meta.
 */
void nvds_copy_classifier_meta(NvDsClassifierMeta *src_classifier_meta,
    NvDsClassifierMeta *dst_classifier_meta);

/**
 * \brief  Makes a deep copy of a label info meta to another label info meta.
 *
 * @param[in] src_label_info    A pointer to the source label info meta.
 * @param[in] dst_label_info    A pointer to the destination label info meta.
 */
void nvds_copy_label_info_meta(NvDsLabelInfo *src_label_info,
    NvDsLabelInfo *dst_label_info);

/**
 * \brief  Makes a deep copy of a display meta to another display meta.
 *
 * @param[in] src_display_meta  A pointer to the source display meta.
 * @param[in] dst_display_meta  A pointer to destination display meta.
 */
void nvds_copy_display_meta(NvDsDisplayMeta *src_display_meta,
    NvDsDisplayMeta *dst_display_meta);

/**
 * \brief  Makes a deep copy of a user meta list to the user meta list
 * in a specified batch meta.
 *
 * @param[in] src_user_meta_list    A pointer to the source user meta list.
 * @param[in] dst_batch_meta        A pointer to the destination batch meta.
 */
void nvds_copy_batch_user_meta_list(NvDsUserMetaList *src_user_meta_list,
    NvDsBatchMeta *dst_batch_meta);

/**
 * \brief  Makes a deep copy of a source user meta list to the user meta list
 * in a specified frame meta.
 *
 * @param[in] src_user_meta_list    A pointer to the source user meta list.
 * @param[in] dst_frame_meta        A pointer to the destination frame meta.
 */
void nvds_copy_frame_user_meta_list(NvDsUserMetaList *src_user_meta_list,
    NvDsFrameMeta *dst_frame_meta);

/**
 * \brief  Makes a deep copy of a source user meta list to the user meta list
 * in a specified object meta.
 *
 * @param[in] src_user_meta_list    A pointer to the source user meta list.
 * @param[in] dst_object_meta       A pointer to the destination object meta.
 */
void nvds_copy_obj_user_meta_list(NvDsUserMetaList *src_user_meta_list,
    NvDsObjectMeta *dst_object_meta);

/**
 * \brief  Makes a deep copy of a source display meta list to the
 *  display meta list in a specified frame meta.
 *
 * @param[in] src_display_meta_list A pointer to the source display meta list.
 * @param[in] dst_frame_meta        A pointer to the destination frame meta.
 */
void nvds_copy_display_meta_list(NvDisplayMetaList *src_display_meta_list,
    NvDsFrameMeta *dst_frame_meta);

/**
 * \brief  Makes a deep copy of a source frame meta list to the frame meta list
 *  in a specified batch meta.
 *
 * @param[in] src_frame_meta_list   A pointer to the source frame meta list.
 * @param[in] dst_batch_meta        A pointer to the destination batch meta.
 */
void nvds_copy_frame_meta_list (NvDsFrameMetaList *src_frame_meta_list,
    NvDsBatchMeta *dst_batch_meta);

/**
 * \brief  Makes a deep copy of a source object meta list to the
 *  object meta list in a specified frame meta.
 *
 * @param[in] src_obj_meta_list A pointer to the source object meta list.
 * @param[in] dst_frame_meta    A pointer to the destination frame meta.
 */
void nvds_copy_obj_meta_list(NvDsObjectMetaList *src_obj_meta_list,
    NvDsFrameMeta *dst_frame_meta);

/**
 * \brief  Makes a deep copy of a source classifier meta list to the
 *  classifier meta list in a specified object meta.
 *
 * @param[in] src_classifier_meta_list  A pointer to the source
 *                                      classifier meta list.
 * @param[in] dst_object_meta           A pointer to the destination
 *                                      object meta.
 */
void nvds_copy_classification_list(NvDsClassifierMetaList *src_classifier_meta_list,
    NvDsObjectMeta *dst_object_meta);

/**
 * \brief  Makes a deep copy of a source label info meta list to the
 *  label info meta list in a specified classifier meta.
 *
 * @param[in] src_label_info_list   A pointer to the source
 *                                  label info meta list.
 * @param[in] dst_classifier_meta   A pointer to the destination
 *                                  classifier meta.
 */
void nvds_copy_label_info_list(NvDsLabelInfoList *src_label_info_list,
    NvDsClassifierMeta *dst_classifier_meta);

/**
 * Generates a unique user metadata type from a specified string describing
 * user-specific metadata.
 *
 * @param[in] meta_descriptor   A pointer to a string describing user-specific
 *                              metadata. The string must be in the format
 *                              @a ORG_NAME.COMPONENT_NAME.METADATA_DESCRIPTION,
 *                              e.g. @c NVIDIA.NVINFER.TENSOR_METADATA.
 */
NvDsMetaType nvds_get_user_meta_type(gchar *meta_descriptor);

#ifdef __cplusplus
}
#endif
#endif

/** @} */
